////////////////////////////////////////////////////////////////////
// Interpreteur de script pour Chrono Cross
////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////
// Nemesis pour Terminus Traduction (tt_nemesis@yahoo.fr)
// Date de création :		30/07/03
// Dernière modification :	24/04/04
////////////////////////////////////////////////////////////////////

// Entete
#include "Script.h"

/* Descriptions							(paramètre(s))
	01) Initialisation des dumps		()
	02) Dump de fichiers				(numéros des Rooms à extraire)
	03) Suppression de fichiers			(numéros des Rooms dumpées)
	04) Ouverture de l'iso				()
	05) Fermeture de l'iso				()
	06) Dump des pointeurs de fichiers	()
	07) Dump de l'entete de l'iso		()
	08) Execution de script				(nom du fichier)
	09) Réinsertion de fichiers			(numéros des Rooms)
	10) Initialisation de la réinsertion()
	11) Récup des pointeurs	de fichiers	()
	12) Mode d'ouverture de l'iso		(lecture|écriture)
	13) Conversion TIM->BMP				(fichier)
	14) Conversion BMP->TIM				(fichier)
	15) Décompression DRP				(dossier|fichiers)
	16) Compression DRP					(dossier|fichiers)
	17) Copie de fichiers entrants		(fichiers)
	18) Copie de fichiers sortants		(fichiers)
	19) Dump de coordonnées	graphiques	(dossier|fichier)
	20) Réinsertion de coordonnées		(dossier|fichier)
	21) Décompression CPT				(dossier|fichiers)
	22) Compression CPT					(dossier|fichiers)
	23) Extraction de textes			(dossier|fichier)
	24) Réinsertion de textes			(dossier|fichier)
	25) Extraction de donnees brutes	(dossier|fichier)
	26) Réinsertion de donnees brutes	(dossier|fichier)
	27) Dump des Rooms					()
	28) Copie entrante des Rooms		()
	29) Extraction des Rooms			()
	30) Décompressions Lzss du script	()
	31) Extraction du scénario			()
	32) Chargement des infos des Rooms  (fichier)
	33) Regroupement des scripts		(fichier)
	34) Séparation des scripts			(fichier)
	35) Dump d'un texte de scénario		(dossier|fichier|table)
	36) Réinsertion d'un "scénario"		(dossier|fichier|table)
	37) Regroupement des descriptions	()
	38) Regroupement des accents		()
	39) Partage par personnages			(fichier)
	40) Regroupement du script/persos	(fichier)
	41) Informations de répartition		(fichier)
	42) Reinsertion des Rooms			()
	43) Recompression Lzss des Rooms	()
	44) Recompression Cpt des Rooms		()
	45) Exécution d'un script			(script)
	46) Copie sortante des Rooms		()
	47) Réinsertion des Rooms			()
	48) Correction des retours de ligne	(fichier)
	49) Réinsertion des accents			()
	50) Modif des pointeurs	de fichiers	()
	51) Suppression des Accents Auto	()
	52) Insertion des Accents Auto		()
	53) Génération des listing du patch	(fichier)
	54) Génération des listing persos	()
	55) Compression Lzss				(dossier|fichier)
	56) Décompression Lzss				(dossier|fichier)
	57) Insertion de video				(numero de room)
	58) Génération des fichiers patch	()
	59) Conversion TIM sans palette BMP	(room|fichier|palette|masque)
	60) Conversion BMP TIM sans palette	(room|fichier|palette|masque)
*/

// Commandes
char *commandes[] = {
	"Dump_Init",		"Dump",				"Dump_Sup",		"Iso_Ouvre",
	"Iso_Ferme",		"Dump_Ptr",			"Dump_Entete",	"Script_Exec",
	"Rein",				"Rein_Init",		"Rein_Ptr",		"Iso_Mode",
	"Tim2Bmp",			"Bmp2Tim",			"Drp_D",		"Drp_C",
	"Copie_I",			"Copie_O",			"Coord_Rein",	"Coord_Dump",
	"Cpt_D",			"Cpt_C",			"Txt_Dump",		"Txt_Rein",
	"Brut_Dump",		"Brut_Rein",		"Rooms_Dump",	"Rooms_Copie_I",
	"Rooms_Cpt_D",		"Rooms_Lzss_D",		"Rooms_Extr",	"Rooms_Infos",
	"Part_Regroupe",	"Part_Partage",		"Scenar_Dump",	"Scenar_Rein",
	"Perso_Regroupe",	"Accent_Regroupe",	"Repart_Partage","Repart_Regroupe",
	"Repart_Infos",		"Rooms_Rescn",		"Rooms_Lzss_C",	"Rooms_Cpt_C",
	"Script",			"Rooms_Copie_O",	"Rooms_Rein",	"Repart_Retours",
	"Accent_Partage",	"Rein_Ptr_M",		"AutoA_Suppr",	"AutoA_Ins",
	"Listing_Genere",	"Listing_Persos",	"Lzss_D",		"Lzss_C",
	"Perso_Partage",	"Str_Insert",		"Listing_Fichs","Raw2Bmp",
	"Bmp2Raw"
};
// Nombre d'arguments
int arguments[] = {
	0,				1,				1,				0,
	0,				0,				0,				1,
	1,				0,				0,				1,
	1,				1,				1,				1,
	1,				1,				1,				1,
	1,				1,				1,				1,
	1,				1,				0,				0,
	0,				0,				0,				1,
	1,				1,				1,				1,
	0,				0,				1,				1,
	1,				0,				0,				0,
	1,				0,				0,				1,
	0,				0,				0,				0,
	1,				0,				1,				1,
	0,				1,				1,				1,
	1
};
// Fonctions sans arguments
void (*fonctions0[]) (void)= {
	Dump_Initialisation,NULL,			NULL,			Iso_Ouvre,
	Iso_Ferme,			Dump_Pointeurs,	Dump_Entete,	NULL,
	NULL,	Reinsertion_Initialisation,	Reinsertion_Pointeurs, NULL,
	NULL,				NULL,			NULL,			NULL,
	NULL,				NULL,			NULL,			NULL,
	NULL,				NULL,			NULL,			NULL,
	NULL,				NULL,			Rooms_Dump,		Rooms_Copie_I,
	Rooms_Cpt_D,		Rooms_Lzss_D,	Rooms_Extraction,NULL,
	NULL,				NULL,			NULL,			NULL,
	Perso_Regroupe,		Accent_Regroupe,NULL,			NULL,
	NULL,			Rooms_Reinsertion,	Rooms_Lzss_C,	Rooms_Cpt_C,
	NULL,				Rooms_Copie_O,	Rooms_Rein,		NULL,
	Accent_Partage,	Reinsertion_Pointeurs_Modif,AutoA_Supprime,AutoA_Insere,
	NULL,				Lst_Persos,		NULL,			NULL,
	Perso_Partage,		NULL,			NULL,			NULL,
	NULL
};
// Fonctions à un argument
void (*fonctions1[]) (char *) = {
	NULL,				Dump_Exec,		Dump_Sup_Exec,	NULL,
	NULL,				NULL,			NULL,			Script_Exec,
	Reinsertion_Exec,	NULL,			NULL,			Iso_Mode,
	Tim_to_Bmp,			Bmp_to_Tim,		Drp_D_Exec,		Drp_C_Exec,
	Fichier_Copie_In,	Fichier_Copie_Out,Coord_Rein,	Coord_Dump,
	Cpt_D_Exec,			Cpt_C_Exec,		Txt_Extraction,	Txt_Reinsertion,
	Brt_Dump,			Brt_Rein,		NULL,			NULL,
	NULL,				NULL,			NULL,			Rooms_Infos,
	Part_Regroupe,		Part_Partage,	Scn_Extr_Exec,	Scn_Rein_Exec,
	NULL,				NULL,			Repart_Partage,	Repart_Regroupe,
	Repart_Infos,		NULL,			NULL,			NULL,
	Script_Interprete,	NULL,			NULL,			Repart_Retours,
	NULL,				NULL,			NULL,			NULL,
	Lst_Genere,			NULL,			Lzss_D_Exec,	Lzss_C_Exec,
	NULL,				Str_Insertion,	Lst_Fichiers,	Raw_to_Bmp,
	Bmp_to_Raw
};

// Type de données pour les commandes
typedef struct {
	char *commande;
	void (*fonction0) (void);
	void (*fonction1) (char *);
} Script_TCommande;

// Liste des commandes possibles
Script_TCommande Script_Commandes[SCRIPT_COMMANDE_NB];
int  Script_Commandes_Nb;

/*------------------------------------------------------------------
  Fonction d'initialisation des commandes de script
------------------------------------------------------------------*/
void Script_Initialisation(void)
{
	int c;

	// Nombre total de commandes
	Script_Commandes_Nb=sizeof(arguments)/sizeof(int);
	// Chargement des commandes
	// avec affichage apres chargement
	for (c=0;c<Script_Commandes_Nb;c++) {
		Script_Commandes[c].commande=commandes[c];
		switch (arguments[c]) {
		case 0:
			Script_Commandes[c].fonction0=fonctions0[c];
			break;
		case 1:
			Script_Commandes[c].fonction1=fonctions1[c];
			break;
		default:
			Main_Message_S("Nombre d'argument erroné\n","",ER);
			break;
		}
		printf(" -> %s\n",Script_Commandes[c].commande);
	};
	Main_Message_S("Initialisation des commandes terminee\n","",OK);
	Main_Ligne();	
}

/*------------------------------------------------------------------
  Fonction d'interpretation d'une ligne de script
--------------------------------------------------------------------
 <- commande = commande a interpreter
------------------------------------------------------------------*/
void Script_Interprete(char *commande)
{
	// Index de commande
	int c=0;
	// Parametre generique
	char param[SCRIPT_ELMT_MAX];
	char nom[SCRIPT_ELMT_MAX];
	// Parametres lus dans le sscanf
	int result;
	
	// Preparation de l'affichage
	Main_Message_S(" -> ","",OK);
	// Recuperation du nom et des parametres
	result=sscanf(commande,
		"%s %s",nom,param);

	if (result<1)
		Main_Message_S("Commande incoherente.\n","",ER);
	else {
		// Recherche de la commande (Attention ordre conditions)
		while (c<Script_Commandes_Nb
			&& strcmp(Script_Commandes[c].commande,nom)!=0)
			c++;
		// Execution ou echec
		if (c==Script_Commandes_Nb)
			Main_Message_S("Commande inconnue.\n","",ER);	
		else
			switch (result) {
			case 1:
				if (Script_Commandes[c].fonction0!=NULL)
					Script_Commandes[c].fonction0();
				else
					Main_Message_S("Arguments incorrects.\n","",ER);	
				break;
			case 2:
				if (Script_Commandes[c].fonction1!=NULL)
					Script_Commandes[c].fonction1(param);
				else
					Main_Message_S("Arguments incorrects.\n","",ER);	
				break;
			default:
				Main_Message_S("Erreur de parametres.\n","",ER);
			};
	};
}

/*------------------------------------------------------------------
  Fonction de lecture d'un script sous forme de fichier
--------------------------------------------------------------------
 <- fich = nom du fichier à ouvrir
------------------------------------------------------------------*/
void Script_Exec(char *fich)
{
	// Fichier du script
	FILE *script_f;
	char fich_complet[100];
	char ligne[SCRIPT_LIGNE_MAX];

	// Ouverture du fichier script
	sprintf(fich_complet, "%s%s.%s",DIR_SCRIPTS,fich,EXT_SCRIPT);
	script_f=fopen(fich_complet,"r");
	// Test d'ouverture
	if (script_f==NULL)
		Main_Message_S("L'ouverture du script a echoue.\n","",ER);
	else {
		printf("Fichier script \"%s\" ouvert.\n",fich_complet);
		// Interpretation de toutes les lignes
		while (fgets(ligne,SCRIPT_LIGNE_MAX,script_f)!=NULL) {
			// Cas d'un commentaire
			if (ligne[0]!=COMMENT)
				Script_Interprete(ligne);
		}
		Main_Message_S("Fin d'interpretation du script.\n","",OK);
		fclose(script_f);
	}
}
